package com.ysd.lis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ysd.common.Result;
import com.ysd.lis.entity.SysParam;
import com.ysd.lis.entity.SysParamField;
import com.ysd.lis.entity.SysParamValue;
import com.ysd.lis.mapper.sys.SysParamFieldMapper;
import com.ysd.lis.mapper.sys.SysParamMapper;
import com.ysd.lis.mapper.sys.SysParamValueMapper;
import com.ysd.lis.request.*;
import com.ysd.lis.service.SysParamValueService;
import com.ysd.util.ToolsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * cold_chain.t_user 服务实现类
 * </p>
 *
 * @author peng
 * @since 2022-02-05
 */
@Service
@Slf4j
public class SysParamValueServiceImpl extends ServiceImpl<SysParamValueMapper, SysParamValue> implements SysParamValueService {

    @Autowired
    SysParamMapper sysParamMapper;
    @Autowired
    SysParamFieldMapper sysParamFieldMapper;

    @Autowired
    SysParamValueMapper sysParamValueMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public Result findSysParamInfoByCode(SysParamParam param) throws JsonProcessingException {
        LambdaQueryWrapper<SysParam> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysParam::getDelFlag, 0).eq(SysParam::getCode, param.getParamCode());
        SysParam sysParam = sysParamMapper.selectOne(queryWrapper);
        SysParamDto sysParamDto = new SysParamDto();
        if (ToolsUtils.isNotEmpty(sysParam)) {
            BeanUtil.copyProperties(sysParam, sysParamDto);
            //查询分组
            LambdaQueryWrapper<SysParamField> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(SysParamField::getDelFlag, 0).eq(SysParamField::getGrade, 0).eq(SysParamField::getPid, sysParam.getId()).orderByAsc(SysParamField::getSeq);
            List<SysParamField> groupList = sysParamFieldMapper.selectList(queryWrapper1);
            if (ToolsUtils.isNotEmpty(groupList)) {
                //查询分组下的字段属性集合
                List<String> groupIds = groupList.stream().map(SysParamField::getId).collect(Collectors.toList());

                LambdaQueryWrapper<SysParamField> queryWrapper2 = new LambdaQueryWrapper<>();
                queryWrapper2.eq(SysParamField::getDelFlag, 0).eq(SysParamField::getGrade, 1).in(SysParamField::getPid, groupIds).orderByAsc(SysParamField::getSeq);
                List<SysParamField> fieldList = sysParamFieldMapper.selectList(queryWrapper2);
                List<SysParamFieldDto> fmItems = new ArrayList<>();
                Integer j = 0;
                for (SysParamField item : fieldList) {
                    SysParamFieldDto fmitm = new SysParamFieldDto();
                    BeanUtil.copyProperties(item, fmitm, "fieldOptions");
                    fmitm.setVisible(1);
                    fmitm.setIsCurrent(j == 0);
                    if (ToolsUtils.isNotEmpty(item.getFieldSource()) && item.getFieldSource().equals("3") && ToolsUtils.isNotEmpty(item.getFieldOptions())) {
                        ObjectMapper objectMapper = new ObjectMapper();
                        SysFieldOptionsDto[] ops = objectMapper.readValue(item.getFieldOptions(), SysFieldOptionsDto[].class);
                        fmitm.setFieldOptions(Arrays.asList(ops));
                    }
                    fmItems.add(fmitm);
                    j++;
                }


                //组合分组
                List<SysParamGroupDto> groupDtoList = new ArrayList<>();
                for (SysParamField field : groupList) {
                    SysParamGroupDto groupDto = new SysParamGroupDto();
                    BeanUtil.copyProperties(field, groupDto);
                    groupDto.setParamFieldList(fmItems.stream().filter(i -> i.getPid().equals(field.getId())).collect(Collectors.toList()));
                    groupDtoList.add(groupDto);
                }
                sysParamDto.setParamGroupList(groupDtoList);
            }
        }


        return Result.succ(1, "查询成功", sysParamDto);
    }

    @Override
    public Result saveSysParamValueList(SysParamDto dto) throws JsonProcessingException {

        List<SysParamValue> editSysParamValueList = new ArrayList<>();
        List<String> fieldIds = new ArrayList<>();
        List<SysParamGroupDto> paramGroupList = dto.getParamGroupList();
        for (SysParamGroupDto groupDto : paramGroupList) {

            List<SysParamValueDto> valueDtoList = groupDto.getParamValueList();
            for (SysParamValueDto valueDto : valueDtoList) {
                SysParamValue paramValue = new SysParamValue();
                BeanUtil.copyProperties(valueDto, paramValue);
                editSysParamValueList.add(paramValue);
            }
            List<SysParamFieldDto> paramFieldList = groupDto.getParamFieldList();
            List<String> stringList = paramFieldList.stream().map(SysParamFieldDto::getId).collect(Collectors.toList());
            fieldIds.addAll(stringList);
        }
        //查询历史数据
        LambdaQueryWrapper<SysParamValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysParamValue::getDelFlag, 0).in(SysParamValue::getFieldId, fieldIds);
        if (ToolsUtils.isNotEmpty(dto.getClassify())) {
            queryWrapper.eq(SysParamValue::getClassifyCode, editSysParamValueList.get(0).getClassifyCode());
        }
        if (ToolsUtils.isNotEmpty(dto.getIsLocal()) && dto.getIsLocal()) {
            queryWrapper.eq(SysParamValue::getLocalComputer, editSysParamValueList.get(0).getLocalComputer());
        }
        List<SysParamValue> oldParamValueList = sysParamValueMapper.selectList(queryWrapper);
        if (ToolsUtils.isNotEmpty(oldParamValueList)) {
            for (SysParamValue paramValue : editSysParamValueList) {
                if (ToolsUtils.isNotEmpty(dto.getClassify())) {
                    Optional<SysParamValue> first = oldParamValueList.stream().filter(o -> (o.getClassifyCode().equals(paramValue.getClassifyCode()) && o.getFieldId().equals(paramValue.getFieldId()))).findFirst();
                    if (first.isPresent()) {
                        SysParamValue paramValue1 = first.get();
                        paramValue.setId(paramValue1.getId());
                    }
                } else {
                    Optional<SysParamValue> first = oldParamValueList.stream().filter(o -> (o.getFieldId().equals(paramValue.getFieldId()))).findFirst();
                    if (first.isPresent()) {
                        SysParamValue paramValue1 = first.get();
                        paramValue.setId(paramValue1.getId());

                    }
                }
            }
        }
        boolean b = this.saveOrUpdateBatch(editSysParamValueList);

        /*if (b) {
            refreshRedis(editSysParamValueList.get(0).getOrgId());
        }*/

        return Result.succ(1, "提交成功", null);
    }

    @Override
    public Result findSysParamInfoValueList(SysParamParam param) {
        HashMap<String, Object> returnMap = new HashMap<>();

        // 1.先判断是否是本地参数：如果是本地参数但是没有传本机名称 则不能查询
        //2.如果传classify 但是没有传 classifyCode 则不能查询
        String classify = param.getClassify();
        //String classifyId = param.getClassifyId();
        String classifyCode = param.getClassifyCode();
        Boolean isLocal = param.getIsLocal();
        String localComputer = param.getLocalComputer();
        boolean isClassifySearch = (ToolsUtils.isEmpty(classify) && ToolsUtils.isEmpty(classifyCode)) || (ToolsUtils.isNotEmpty(classify) && ToolsUtils.isNotEmpty(classifyCode));
        boolean isLocalSearch = ToolsUtils.isEmpty(isLocal) || !isLocal || (isLocal && ToolsUtils.isNotEmpty(localComputer));


        if (isClassifySearch && isLocalSearch) {
            List<SysParamValueDto> fmValues = new ArrayList<>();
            MPJLambdaWrapper<SysParamValue> queryWrapper = new MPJLambdaWrapper<>();
            queryWrapper.selectAll(SysParamValue.class).leftJoin(SysParamField.class, "sf", SysParamField::getId, SysParamValue::getFieldId).leftJoin(SysParamField.class, "sg", SysParamField::getId, SysParamField::getPid).leftJoin(SysParam.class, "sp", SysParam::getId, SysParamField::getPid);
            queryWrapper.eq(SysParamValue::getDelFlag, 0).eq("sf.DEL_FLAG", 0).eq("sg.DEL_FLAG", 0).eq("sp.DEL_FLAG", 0).eq("sf.grade", 1).eq("sg.grade", 0).eq(SysParam::getCode, param.getParamCode());
            if (ToolsUtils.isNotEmpty(classifyCode)) {
                queryWrapper.eq(SysParamValue::getClassifyCode, classifyCode);
            }
            if (ToolsUtils.isNotEmpty(localComputer)) {
                queryWrapper.eq(SysParamValue::getLocalComputer, localComputer);
            }
            List<SysParamValue> valueList = sysParamValueMapper.selectList(queryWrapper);
            if (ToolsUtils.isNotEmpty(valueList)) {
                for (SysParamValue sysParamValue : valueList) {
                    SysParamValueDto valueDto = new SysParamValueDto();
                    BeanUtil.copyProperties(sysParamValue, valueDto);
                    fmValues.add(valueDto);
                }
            }
            returnMap.put("fmValues", fmValues);

        }
        //显示所有计算机列表
        Boolean isComputer = param.getIsComputer();
        if (ToolsUtils.isNotEmpty(isComputer) && isComputer) {
//            QueryWrapper<SysParamValue>  qw  = new QueryWrapper<>();
//            qw.select("DISTINCT LOCAL_COMPUTER").lambda().eq(SysParamValue::getDelFlag,0).eq(SysParamValue::getIsLocal,true);
//            List<SysParamValue> LocalComputerList = sysParamValueMapper.selectList(qw);
//            if(ToolsUtils.isNotEmpty(LocalComputerList)){
//
//                returnMap.put("LocalComputerList",LocalComputerList);
//            }
            MPJLambdaWrapper<SysParamValue> qw = new MPJLambdaWrapper<>();
            qw.select("distinct t.LOCAL_COMPUTER").leftJoin(SysParamField.class, "sf", SysParamField::getId, SysParamValue::getFieldId).leftJoin(SysParamField.class, "sg", SysParamField::getId, SysParamField::getPid).leftJoin(SysParam.class, "sp", SysParam::getId, SysParamField::getPid);
            qw.eq(SysParamValue::getDelFlag, 0).eq("sf.DEL_FLAG", 0).eq("sg.DEL_FLAG", 0).eq("sp.DEL_FLAG", 0).eq("sf.grade", 1).eq("sg.grade", 0).eq(SysParam::getCode, param.getParamCode()).eq(SysParamValue::getIsLocal, isComputer);

            List<SysParamValue> LocalComputerList = sysParamValueMapper.selectList(qw);
            returnMap.put("LocalComputerList", LocalComputerList);

        }
        return Result.succ(1, "查询成功", returnMap);
    }

    @Override
    public Boolean refreshRedis(String orgId) {
        //0.组织机构Id
        if (ToolsUtils.isNotEmpty(orgId)) {
            // 1. 删除旧的 system:options: 参数
            Set<String> keysToDelete = redisTemplate.keys("system:options:" + orgId + ":*");
            if (keysToDelete != null && !keysToDelete.isEmpty()) {
                redisTemplate.delete(keysToDelete);
                System.out.println("Old system options removed from Redis.");
            }

            Map<String, Map<String, String>> options = findSysParamFieldAndValueList();
            options.forEach((key, value) -> {
                String redisKey = "system:options:" + key; // 格式化 Redis Key
                value.forEach((k, v) -> {
                    redisTemplate.opsForValue().set(redisKey + ":" + k, v);
                });
            });
            return true;
        }
        return false;
    }

    @Override
    public Result findSysParamFieldAndValueByCode(SysParamParam param) throws JsonProcessingException {
        MPJLambdaWrapper<SysParamValue> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(SysParamField.class, "sf").selectAs(SysParamValue::getId, SysParamFieldValueDto::getValueId).selectAs(SysParamValue::getClassify, SysParamFieldValueDto::getClassify).selectAs(SysParamValue::getClassifyId, SysParamFieldValueDto::getClassifyId).selectAs(SysParamValue::getClassifyCode, SysParamFieldValueDto::getClassifyCode).selectAs(SysParamValue::getValue, SysParamFieldValueDto::getValue).selectAs(SysParamValue::getDataType, SysParamFieldValueDto::getDataType).selectAs(SysParamValue::getIsLocal, SysParamFieldValueDto::getIsLocal).selectAs(SysParamValue::getLocalComputer, SysParamFieldValueDto::getLocalComputer).leftJoin(SysParamField.class, "sf", SysParamField::getId, SysParamValue::getFieldId).leftJoin(SysParamField.class, "sg", SysParamField::getId, SysParamField::getPid).leftJoin(SysParam.class, "sp", SysParam::getId, SysParamField::getPid);
        queryWrapper.eq(SysParamValue::getDelFlag, 0).eq("sf.DEL_FLAG", 0).eq("sg.DEL_FLAG", 0).eq("sp.DEL_FLAG", 0).eq("sf.grade", 1).eq("sg.grade", 0).eq(SysParam::getCode, param.getParamCode());
        if (ToolsUtils.isNotEmpty(param.getClassifyCode())) {
            queryWrapper.eq(SysParamValue::getClassifyCode, param.getClassifyCode());
        }
        if (ToolsUtils.isNotEmpty(param.getLocalComputer())) {
            queryWrapper.eq(SysParamValue::getLocalComputer, param.getLocalComputer());
        }
        if (ToolsUtils.isNotEmpty(param.getField())) {
            queryWrapper.eq("sf.FIELD", param.getField());
        }
        List<SysParamFieldValueDto> valueList = sysParamValueMapper.selectJoinList(SysParamFieldValueDto.class, queryWrapper);
        return Result.succ(1, "查询成功", valueList);
    }

    public List<SysParamFieldValueDto> findSysParamFieldAndValueListByCode(SysParamParam param) throws JsonProcessingException {
        MPJLambdaWrapper<SysParamValue> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(SysParamField.class, "sf").selectAs(SysParamValue::getId, SysParamFieldValueDto::getValueId).selectAs(SysParamValue::getClassify, SysParamFieldValueDto::getClassify).selectAs(SysParamValue::getClassifyId, SysParamFieldValueDto::getClassifyId).selectAs(SysParamValue::getClassifyCode, SysParamFieldValueDto::getClassifyCode).selectAs(SysParamValue::getValue, SysParamFieldValueDto::getValue).selectAs(SysParamValue::getDataType, SysParamFieldValueDto::getDataType).selectAs(SysParamValue::getIsLocal, SysParamFieldValueDto::getIsLocal).selectAs(SysParamValue::getLocalComputer, SysParamFieldValueDto::getLocalComputer).leftJoin(SysParamField.class, "sf", SysParamField::getId, SysParamValue::getFieldId).leftJoin(SysParamField.class, "sg", SysParamField::getId, SysParamField::getPid).leftJoin(SysParam.class, "sp", SysParam::getId, SysParamField::getPid);
        queryWrapper.eq(SysParamValue::getDelFlag, 0).eq("sf.DEL_FLAG", 0).eq("sg.DEL_FLAG", 0).eq("sp.DEL_FLAG", 0).eq("sf.grade", 1).eq("sg.grade", 0).eq(SysParam::getCode, param.getParamCode());
        if (ToolsUtils.isNotEmpty(param.getClassifyCode())) {
            queryWrapper.eq(SysParamValue::getClassifyCode, param.getClassifyCode());
        }
        if (ToolsUtils.isNotEmpty(param.getLocalComputer())) {
            queryWrapper.eq(SysParamValue::getLocalComputer, param.getLocalComputer());
        }
        if (ToolsUtils.isNotEmpty(param.getField())) {
            queryWrapper.eq("sf.FIELD", param.getField());
        }
        List<SysParamFieldValueDto> valueList = sysParamValueMapper.selectJoinList(SysParamFieldValueDto.class, queryWrapper);
        return valueList;
    }

    private Map<String, Map<String, String>> findSysParamFieldAndValueList() {
        MPJLambdaWrapper<SysParamValue> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(SysParamField.class, "sf");
        queryWrapper.selectAs(SysParamValue::getId, SysParamFieldValueDto::getValueId);
        queryWrapper.selectAs(SysParamValue::getClassify, SysParamFieldValueDto::getClassify);
        queryWrapper.selectAs(SysParamValue::getClassifyId, SysParamFieldValueDto::getClassifyId);
        queryWrapper.selectAs(SysParamValue::getClassifyCode, SysParamFieldValueDto::getClassifyCode);
        queryWrapper.selectAs(SysParamValue::getValue, SysParamFieldValueDto::getValue);
        queryWrapper.selectAs(SysParamValue::getDataType, SysParamFieldValueDto::getDataType);
        queryWrapper.selectAs(SysParamValue::getIsLocal, SysParamFieldValueDto::getIsLocal);
        queryWrapper.selectAs(SysParamValue::getLocalComputer, SysParamFieldValueDto::getLocalComputer);
        queryWrapper.selectAs(SysParam::getCode, SysParamFieldValueDto::getSysParamCode);
        queryWrapper.selectAs(SysParam::getModuleId, SysParamFieldValueDto::getSysParamModuleId);
        queryWrapper.leftJoin(SysParamField.class, "sf", SysParamField::getId, SysParamValue::getFieldId);
        queryWrapper.leftJoin(SysParamField.class, "sg", SysParamField::getId, SysParamField::getPid);
        queryWrapper.leftJoin(SysParam.class, "sp", SysParam::getId, SysParamField::getPid);
        queryWrapper.eq(SysParamValue::getDelFlag, 0);
        queryWrapper.eq("sf.DEL_FLAG", 0);
        queryWrapper.eq("sg.DEL_FLAG", 0);
        queryWrapper.eq("sp.DEL_FLAG", 0);
        //queryWrapper.eq("sf.grade", 1);
        //queryWrapper.eq("sg.grade", 0);
        List<SysParamFieldValueDto> valueList = sysParamValueMapper.selectJoinList(SysParamFieldValueDto.class, queryWrapper);

        Map<String, List<SysParamFieldValueDto>> groupList = valueList.stream().collect(Collectors.groupingBy(SysParamFieldValueDto::getOrgId));
        Map<String, Map<String, String>> optionsMap = new HashMap<>();

        for (Map.Entry<String, List<SysParamFieldValueDto>> mList : groupList.entrySet()) {
            Map<String, String> options = new HashMap<>();

            for (SysParamFieldValueDto m : mList.getValue()) {
                String key = "";
                if (ToolsUtils.isNotEmpty(m.getSysParamCode())) {
                    key += m.getSysParamCode();
                }
                if (ToolsUtils.isNotEmpty(m.getField())) {
                    key += "." + m.getField();
                }
                if (ToolsUtils.isNotEmpty(m.getClassifyCode())) {
                    key += "." + m.getClassifyCode();
                }
                if (ToolsUtils.isEmpty(key)) {
                    continue;
                }
                options.put(key, m.getValue());
            }
            optionsMap.put(mList.getKey(), options);
        }


        return optionsMap;
    }
}
